#include <signal.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#define SERVER_PORT 4321 //服务器端口号
#define Client_PORT 6383 //客户端的端口号
#define BUFFER_SIZE 1024 //缓存



int sockfd, sendbytes, recvbytes; // ip通讯fd， 发送信息状态， 获取信息状态
char get_buf[BUFFER_SIZE]; //从服务器发送的信息
char send_buf[BUFFER_SIZE];//发送数据的缓存
struct hostent *host;//主机的信息
struct sockaddr_in serv_addr, client_addr; //主机与客户端接发送信息地址端口
int send_awser_status; //判断是否可以发送答案
int testing_status; //考试状态 -1退出 0无连接 1连接成功 2准备完毕
int error_num = 0;//错误信号次数
char student_name[64]; //学生名字
char student_num[15]; //学生学号
int problem_test_num =0; //0表示没有发完题 1表示发完题
int server_client_exit =0;
int really_to = 0;


int send_server(char *buf);
/*定义信号*/
void my_func(int sign_no)
{
	if(sign_no == SIGINT)
	{
		error_num++;
		printf("错误操作\n");
	}
	else if(sign_no == SIGQUIT)
	{
		error_num++;
		printf("错误操作\n");
	}
	else if(sign_no == SIGSTOP)
	{
		error_num++;
		printf("错误操作\n");
	}
	if(error_num == 3)
	{
		send_server("error");/*错误3次向服务器发送一次警告*/
		printf("向服务器发送警告\n");
		error_num=0;
	}
}

/*进行客户端的倒计时*/
int count_down()
{
	int second =10;
	while(second >= 0)
	{
		printf("正式考试倒计时：%d s\n",second);
		second--; //减一秒
		sleep(1);
	}
	printf("现在正式考试\n");
    return 2;
}

//开个线程获取错误操作
void *get_error(void *arg)
{
    while (1)
    {
        //客户端正式考试
        if(testing_status == 2)
        {
            break;
        }
        sleep(1);
    }
    signal(SIGINT, my_func);
	signal(SIGQUIT, my_func);
	signal(SIGSTOP, my_func);
    
    while (1)
    {
        if(testing_status == -1)
        {
            break;
        }
        sleep(1);
    }
    pthread_exit(NULL);
}

/*开线程获取服务器的发来的信息*/
void *get_server( void *arg)
{
    int problem_num = 0;
    /*循环获取服务器信息*/
    while (1)
    {
        memset(get_buf, 0, BUFFER_SIZE);
        if((recvbytes = recv(sockfd, get_buf, BUFFER_SIZE, 0))== -1)
        {
            perror("recv");
            break;
        }

        //处理来自服务器的消息

        //服务器连上了
        if(strncmp(get_buf,"success",strlen("success")) == 0)
        {
            testing_status = 1;
        }
        else if (strncmp(get_buf,"problemover",strlen("problemover")) == 0)
        {
            problem_test_num = 1;
        }
        //发送学号
        else if(strncmp(get_buf,"student_num",strlen("student_num")) == 0)
        {
            really_to = 1;
        }

         //发送名字
        else if(strncmp(get_buf,"student_name",strlen("student_name")) == 0)
        {
           really_to = 2;
        }
        //可以正式考试
        else if(strncmp(get_buf,"time_down",strlen("time_down")) == 0)
        {
            testing_status = count_down();
            printf("testing_status%d",testing_status);
        }

        //得到题目
        else if(strncmp(get_buf, "problem",7) == 0)
        {
            printf("题目%d:\n %s\n",problem_num,get_buf);
            send_awser_status =1;
            problem_num++;
        }
        
        //处理服务器的连接状态提醒
        else if(strncmp(get_buf, "status", 6) == 0)
        {
            printf("%s\n", get_buf+strlen("status"));
        }

        //退出线程
        else if(strncmp(get_buf, "exit", 4) == 0) 
        {
            testing_status = -1;
            printf("准备退出程序\n");
            
            break;
        }
        else if(strlen(get_buf)!=0)
        {
            printf("%s\n",get_buf);
        }     
    }
    pthread_exit(NULL);
}


/*getscanf 线程输入数据*/
void *get_scanf(void *arg)
{
	while (1)
    {
         //发送信息给服务器
         memset(send_buf, 0, BUFFER_SIZE);

         //发送是答案和操作
         if (problem_test_num == 0)
         {
           char answer[10];
           printf("输入要发送的信息：");
           scanf("%s",send_buf);
           if(strlen(send_buf) == 1)
            {
                    sprintf(answer, "answer%s" , send_buf);
                    send_server(answer);
                }
                else
                {
                    send_server(send_buf);
                }        
           }
            //发送是操作
          else if(problem_test_num == 1)
          {
             printf("输入要发送的信息：");
             scanf("%s",send_buf);
             send_server(send_buf);
          }
        sleep(1);
	}
}

int send_server(char *buf)
{
    if((sendbytes = (send(sockfd, buf, BUFFER_SIZE, 0) )) == -1)
    {
        perror("send");
    }
    return sendbytes;
}

int main(int argc, char *argv[])
{
	
    testing_status = 0;
    send_awser_status =0;

    /*地址解析*/
    if((host = gethostbyname(argv[1])) == NULL)
    {
        perror("gethostbyname...");
        exit(1);
    }

    /*创建socket*/
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0))== -1)
    {
        perror("socket");
        exit(1);
    
    }

    /*设置客户端socket_in的参数*/
    client_addr.sin_family = host->h_addrtype;
    client_addr.sin_port = htons(Client_PORT);
    client_addr.sin_addr.s_addr = INADDR_ANY; //监听0.0.0.0 全部网卡地址
    memset(&(client_addr.sin_zero), 0, 8);
    int i =1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
    /*客户端进行绑定bind()*/
    if(bind(sockfd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("bind");
        exit(1);
    } 

    /*设置socketaddr_in的结构体参数*/
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVER_PORT);
    
    //头文件中有 #define h_addr addr_list[0]
    serv_addr.sin_addr = *((struct in_addr *)host -> h_addr);
    
    memset(&(serv_addr.sin_zero), 0, 8);

    /*调用connect进行主动服务器发起连接*/
    if(connect(sockfd, (struct sockaddr *)&serv_addr,sizeof(struct sockaddr)) == -1)
    {
        perror("connect");
        exit(1);
    }
    pthread_t thread[3];
    int res; //线程表示符
    res = pthread_create(&thread[0], NULL, get_server, (void*)0);
    if(res != 0)
    {
        perror("pthread");
        printf("创建接受信息线程失败\n");
        exit(1);
    }
    res = pthread_create(&thread[1], NULL, get_error, (void*)0);
    if(res != 0)
    {
        perror("pthread");
        printf("创建接受信息线程失败\n");
        exit(1);
    }
    /*
    signal(SIGINT, my_func);
	signal(SIGQUIT, my_func);
	signal(SIGSTOP, my_func);
    */

   /*输入学号姓名*/
   really_to =  0;
    while(1)
    {
        if(testing_status == 1)
        {
            char number[15];
            char name[64];
            printf("请输入你的学号：\n");
            scanf("%s",number);
            sprintf(student_num,"student_num%s",number);
            printf("请输入你的名字:\n");
            scanf("%s",name);
            sprintf(student_name,"student_name%s",name);
			break;
            
        }
        sleep(1);
        
    }
    while(1)
    {
		if(really_to == 1)
        {
			send_server(student_num);
		}
		else if(really_to == 2)
		{
			send_server(student_name);
			break;
		}
        sleep(1);     
    }

    /*准备考试*/
    problem_test_num = 0;
    
	/*创建线程进行输入数据*/
	 while(1)
	 {
		 if(testing_status == 2)
		 {
			res = pthread_create(&thread[2], NULL, get_scanf, (void*)0);
			if(res != 0)
			{
				perror("pthread");
				printf("创建接受信息线程失败\n");
				exit(1);
			}
			break;
		 }
		 sleep(1);
	}
    while (1)
    {
        /**
        if(testing_status == 1)
        {
            char number[15];
            char name[64];
            printf("请输入你的学号：\n");
            scanf("%s",number);
            sprintf(student_num,"student_num%s",number);
            printf("请输入你的名字:\n");
            scanf("%s",name);
            sprintf(student_name,"student_name%s",name);
            sleep(1);
        }
        */
        
        if(testing_status == -1)
        {
            printf("退出程序\n");
            break;
        }
        sleep(1);
    }
    
    
    
    close(sockfd);
    exit(0);

}
